package com.irdstudio.efp.esb.api.rest.psd.query;
import java.math.BigDecimal;

import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.irdstudio.basic.framework.core.constant.ESBConstant;
import com.irdstudio.basic.framework.core.constant.EsbRetCodeStandard;
import com.irdstudio.basic.framework.core.exception.BizException;
import com.irdstudio.efp.ctr.service.facade.CtrLoanContService;
import com.irdstudio.efp.ctr.service.vo.CtrLoanContVO;
import com.irdstudio.efp.esb.api.bean.psd.query.req.PsdCompositeQryReqBean;
import com.irdstudio.efp.esb.api.bean.psd.query.resp.PsdCompositeQryRespBean;
import com.irdstudio.efp.esb.api.bean.psd.query.resp.composite.*;
import com.irdstudio.efp.esb.api.common.EsbRespServiceBeanCreator;
import com.irdstudio.efp.esb.api.rest.EsbController;
import com.irdstudio.efp.esb.common.constant.EsbBizEnums;
import com.irdstudio.efp.esb.common.constant.EsbSysHeadEnums;
import com.irdstudio.efp.esb.common.server.req.EsbReqServiceBean;
import com.irdstudio.efp.esb.common.server.resp.EsbRespServiceBean;
import com.irdstudio.efp.limit.service.facade.LmtPrdContService;
import com.irdstudio.efp.limit.service.vo.LmtPrdContVO;
import com.irdstudio.efp.nls.service.facade.NlsApplyInfoService;
import com.irdstudio.efp.nls.service.facade.psd.PreNlsCreditInfoService;
import com.irdstudio.efp.nls.service.facade.sx.NlsCreditInfoService;
import com.irdstudio.efp.nls.service.vo.NlsApplyInfoVO;
import com.irdstudio.efp.nls.service.vo.psd.PreNlsCreditInfoVO;
import com.irdstudio.efp.nls.service.vo.sx.NlsCreditInfoVO;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.BindingResult;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 需求编号：【2019D1218】（普税贷需求）
 * 问题编号：【2019D1218】（普税贷综合进度查询查询）
 * 开发人员：【xiaojunhui】
 * 创建日期：【2020/06/10 10:11】
 * 功能描述：
 */

@RestController
@RequestMapping("esb")
public class PsdCompositeQryController implements EsbController {
    /**
     * 日志信息
     */
    private final Logger logger = LoggerFactory.getLogger(PsdCompositeQryController.class);

    @Autowired
    private PreNlsCreditInfoService preNlsCreditInfoService;

    @Autowired
    private NlsCreditInfoService nlsCreditInfoService;

    @Autowired
    private CtrLoanContService ctrLoanContService;

    @Autowired
    private LmtPrdContService lmtPrdContService;

    @Autowired
    private NlsApplyInfoService nlsApplyInfoService;

    @ModelAttribute("esbReqServiceBean")
    public EsbReqServiceBean getReqEsbHeadBean(HttpServletRequest request) {
        logger.info("获取ESB请求系统头和请求应用头对象!");
        EsbReqServiceBean esbReqServiceBean = (EsbReqServiceBean) request.getAttribute("esbReqServiceBean");
        return esbReqServiceBean;
    }

    @ModelAttribute("psdCompositeQryReqBean")
    public PsdCompositeQryReqBean getReqEsbBodyBean(HttpServletRequest request) {
        logger.info("获取ESB请求体！");
        String esbReqBody = (String) request.getAttribute("esbReqBody");
        return JSONObject.parseObject(esbReqBody, PsdCompositeQryReqBean.class);
    }


    @PostMapping("/SERVICE_30230099_01")
    public EsbRespServiceBean doRecv(@Validated @ModelAttribute("esbReqServiceBean") EsbReqServiceBean esbReqServiceBean, BindingResult bindingResult1,
                                     @Validated @ModelAttribute("psdCompositeQryReqBean") PsdCompositeQryReqBean psdCompositeQryReqBean, BindingResult bindingResult2, Exception exception) {
        // 预授信申请信息查询响应信息
        PsdCompositeQryRespBean respBean = new PsdCompositeQryRespBean();
        try {
            // 参数校验
            if (!Objects.isNull(exception)) {
                throw exception;
            }
            // 设置系统头对象
            setSysHeadFieldThreadLocal(esbReqServiceBean);
            //根据查询接口查询类型判断查询参数
            String paramType = psdCompositeQryReqBean.getParamType();
            // 跟据参数类型查询最新一笔的预授信申请记录
            PreNlsCreditInfoVO preNlsCreditInfoVO = qryPreNlsCreditInfoByParam(psdCompositeQryReqBean);
            if (Objects.isNull(preNlsCreditInfoVO)) {
                return successHandler(esbReqServiceBean, respBean);
            }
            //设置预授信申请信息
            respBean.setComPreNlsCreditInfo(getComPreNlsCreditInfo(preNlsCreditInfoVO));
            //根据预授信查询授信申请记录
            List<NlsCreditInfoVO> nlsCreditInfoVOS = nlsCreditInfoService.queryByPreLmtApplySeq(preNlsCreditInfoVO.getApplySeq());
            if (nlsCreditInfoVOS == null || nlsCreditInfoVOS.isEmpty()) {
                return successHandler(esbReqServiceBean, respBean);
            }
            //根据时间排序取最新一条数据
            NlsCreditInfoVO nlsCreditInfoVO = nlsCreditInfoVOS.stream().sorted(new Comparator<NlsCreditInfoVO>() {
                @Override
                public int compare(NlsCreditInfoVO o1, NlsCreditInfoVO o2) {
                    LocalDateTime localDateTime1 = LocalDateTime.parse(o1.getCreateTime(), DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
                    LocalDateTime localDateTime2 = LocalDateTime.parse(o2.getCreateTime(), DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
                    if (localDateTime1.isAfter(localDateTime2)) {
                        return -1;
                    }
                    if (localDateTime1.isBefore(localDateTime2)) {
                        return 1;
                    }
                    return 0;
                }
            }).limit(1).collect(Collectors.toList()).get(0);
            //设置授信申请记录信息
            ComNlsCreditInfo comNlsCreditInfo = getComNlsCreditInfo(nlsCreditInfoVO);
            respBean.setComNlsCreditInfo(comNlsCreditInfo);
            //根据授信申请信息查询授信合同信息
            CtrLoanContVO ctrLoanContVOPkParam = new CtrLoanContVO();
            ctrLoanContVOPkParam.setContNo(nlsCreditInfoVO.getLmtApplySeq());
            CtrLoanContVO ctrLoanContVO = ctrLoanContService.queryContNo(ctrLoanContVOPkParam);
            if (!Objects.isNull(ctrLoanContVO)) {
                //封装授信合同信息
                respBean.setComSxCtrInfo(getComSxCtrInfo(ctrLoanContVO));
            }
            //根据授信申请信息查询授信额度信息
            LmtPrdContVO lmtPrdContVOPkParam = new LmtPrdContVO();
            lmtPrdContVOPkParam.setLmtApplySeq(nlsCreditInfoVO.getLmtApplySeq());
            LmtPrdContVO lmtPrdContVO = lmtPrdContService.queryByPk(lmtPrdContVOPkParam);
            if (!Objects.isNull(lmtPrdContVO)) {
                respBean.setComLmtPrdCont(getComLmtPrdCont(lmtPrdContVO));
            }
            //根据授信申请信息查询支用申请列表
            List<NlsApplyInfoVO> nlsApplyInfoVOS = nlsApplyInfoService.queryAllByLmtApplySeq(nlsCreditInfoVO.getLmtApplySeq());
            if (nlsApplyInfoVOS != null && !nlsApplyInfoVOS.isEmpty()) {
                ArrayList<ComNlsApplyInfo> comNlsApplyInfos = new ArrayList<>();
                for (NlsApplyInfoVO nlsApplyInfoVO : nlsApplyInfoVOS) {
                    comNlsApplyInfos.add(getComNlsApplyInfo(nlsApplyInfoVO));
                }
                respBean.setComNlsApplyInfos(comNlsApplyInfos);
            }
            return successHandler(esbReqServiceBean, respBean);
        } catch (BizException e) {
            e.printStackTrace();
            return failureHandler(esbReqServiceBean, respBean, e, EsbRetCodeStandard.JKYDCSJYBTG, e.getMessage());
        } catch (Exception e) {
            e.printStackTrace();
            return failureHandler(esbReqServiceBean, respBean, e, EsbRetCodeStandard.SJCLYC, e.getMessage());
        }
    }

    private ComNlsApplyInfo getComNlsApplyInfo(NlsApplyInfoVO nlsApplyInfoVO) {
        ComNlsApplyInfo comNlsApplyInfo = new ComNlsApplyInfo();
        comNlsApplyInfo.setApplySeq(nlsApplyInfoVO.getApplySeq());
        comNlsApplyInfo.setLmtApplySeq(nlsApplyInfoVO.getLmtApplySeq());
        comNlsApplyInfo.setApplyDate(nlsApplyInfoVO.getApplyDate());
        comNlsApplyInfo.setApplyTime(nlsApplyInfoVO.getApplyTime());
        comNlsApplyInfo.setApplyAmt(nlsApplyInfoVO.getApplyAmt());
        comNlsApplyInfo.setNlsApplyState(nlsApplyInfoVO.getNlsApplyState());
        comNlsApplyInfo.setRefuseCause(nlsApplyInfoVO.getRefuseCause());
        comNlsApplyInfo.setLoanTerm(nlsApplyInfoVO.getLoanTerm());
        comNlsApplyInfo.setLoanTermType(nlsApplyInfoVO.getLoanTermType());
        comNlsApplyInfo.setLoanPurpose(nlsApplyInfoVO.getLoanPurpose());
        comNlsApplyInfo.setLoanRate(nlsApplyInfoVO.getLoanRate());
        comNlsApplyInfo.setRepayMethod(nlsApplyInfoVO.getRepaymentMode());
        comNlsApplyInfo.setDnSts(nlsApplyInfoVO.getDnSts());
        comNlsApplyInfo.setAmountOfLoan(nlsApplyInfoVO.getAmountOfLoan());
        return comNlsApplyInfo;
    }

    private ComLmtPrdCont getComLmtPrdCont(LmtPrdContVO lmtPrdContVO) {
        ComLmtPrdCont comLmtPrdCont = new ComLmtPrdCont();
        comLmtPrdCont.setLmtContNo(lmtPrdContVO.getLmtContNo());
        comLmtPrdCont.setLmtApplySeq(lmtPrdContVO.getLmtApplySeq());
        comLmtPrdCont.setLmtAmt(lmtPrdContVO.getLmtAmt());
        comLmtPrdCont.setAvailAmt(lmtPrdContVO.getAvailAmt());
        comLmtPrdCont.setPreOccAmt(lmtPrdContVO.getPreOccAmt());
        comLmtPrdCont.setOccAmt(lmtPrdContVO.getOccAmt());
        comLmtPrdCont.setCyclicFlg(lmtPrdContVO.getCyclicFlg());
        comLmtPrdCont.setCurrencyType(lmtPrdContVO.getCurrencyType());
        comLmtPrdCont.setTerm(lmtPrdContVO.getTerm());
        comLmtPrdCont.setTermType(lmtPrdContVO.getTermType());
        comLmtPrdCont.setRateY(lmtPrdContVO.getRateY());
        comLmtPrdCont.setRepaymentMode(lmtPrdContVO.getRepaymentMode());
        comLmtPrdCont.setRepaymentPeriod(lmtPrdContVO.getRepaymentPeriod());
        comLmtPrdCont.setRepaymentPeriodType(lmtPrdContVO.getRepaymentPeriodType());
        comLmtPrdCont.setRepaymentDayType(lmtPrdContVO.getRepaymentDayType());
        comLmtPrdCont.setRepaymentDay(lmtPrdContVO.getRepaymentDay());
        comLmtPrdCont.setLmtStatus(lmtPrdContVO.getLmtStatus());
        comLmtPrdCont.setStartDate(lmtPrdContVO.getStartDate());
        comLmtPrdCont.setExpireDate(lmtPrdContVO.getExpireDate());
        comLmtPrdCont.setSignDate(lmtPrdContVO.getSignDate());
        return comLmtPrdCont;
    }

    private ComSxCtrInfo getComSxCtrInfo(CtrLoanContVO ctrLoanContVO) {
        ComSxCtrInfo comSxCtrInfo = new ComSxCtrInfo();
        comSxCtrInfo.setContNo(ctrLoanContVO.getContNo());
        comSxCtrInfo.setLmtContNo(ctrLoanContVO.getLmtContNo());
        comSxCtrInfo.setContStatus(ctrLoanContVO.getContState());
        comSxCtrInfo.setSignDate(ctrLoanContVO.getSignDate());
        return comSxCtrInfo;
    }

    private ComNlsCreditInfo getComNlsCreditInfo(NlsCreditInfoVO nlsCreditInfoVO) {
        ComNlsCreditInfo comNlsCreditInfo = new ComNlsCreditInfo();
        comNlsCreditInfo.setLmtApplySeq(nlsCreditInfoVO.getLmtApplySeq());
        comNlsCreditInfo.setRecvAccount(nlsCreditInfoVO.getRecvAccount());
        comNlsCreditInfo.setDnAccount(nlsCreditInfoVO.getDnAccount());
        comNlsCreditInfo.setApplyAmt(nlsCreditInfoVO.getApplyAmt());
        comNlsCreditInfo.setApproveAmt(nlsCreditInfoVO.getApproveAmt());
        comNlsCreditInfo.setApplyTerm(nlsCreditInfoVO.getApplyTerm());
        comNlsCreditInfo.setTermType(nlsCreditInfoVO.getTermType());
        comNlsCreditInfo.setApplyTateY(nlsCreditInfoVO.getApplyRateY());
        comNlsCreditInfo.setApproveRateY(nlsCreditInfoVO.getApproveRateY());
        comNlsCreditInfo.setCurrencyType(nlsCreditInfoVO.getCurrencyType());
        comNlsCreditInfo.setRepaymentMode(nlsCreditInfoVO.getRepaymentMode());
        comNlsCreditInfo.setRepaymentPeriod(nlsCreditInfoVO.getRepaymentPeriod());
        comNlsCreditInfo.setRepaymentPeriodType(nlsCreditInfoVO.getRepaymentPeriodType());
        comNlsCreditInfo.setRepaymentDayType(nlsCreditInfoVO.getRepaymentDayType());
        comNlsCreditInfo.setRepaymentDay(nlsCreditInfoVO.getRepaymentDay());
        comNlsCreditInfo.setApprvDate(nlsCreditInfoVO.getApprvDate());
        comNlsCreditInfo.setApprvSts(nlsCreditInfoVO.getApprvSts());
        comNlsCreditInfo.setApplyDate(nlsCreditInfoVO.getApplyDate());
        comNlsCreditInfo.setRejectReason(nlsCreditInfoVO.getRejectReason());
        return comNlsCreditInfo;
    }

    private ComPreNlsCreditInfo getComPreNlsCreditInfo(PreNlsCreditInfoVO preNlsCreditInfoVO) {
        ComPreNlsCreditInfo comPreNlsCreditInfo = new ComPreNlsCreditInfo();
        comPreNlsCreditInfo.setApplySeq(preNlsCreditInfoVO.getApplySeq());
        comPreNlsCreditInfo.setTaxIdentificationNumber(preNlsCreditInfoVO.getTaxIdentificationNumber());
        comPreNlsCreditInfo.setEnterpriseName(preNlsCreditInfoVO.getEnterpriseName());
        comPreNlsCreditInfo.setSocialCreditCode(preNlsCreditInfoVO.getSocialCreditCode());
        comPreNlsCreditInfo.setRegistration(preNlsCreditInfoVO.getRegistration());
        comPreNlsCreditInfo.setRecommenderAccount(preNlsCreditInfoVO.getRecommenderAccount());
        comPreNlsCreditInfo.setRecommenderOrgid(preNlsCreditInfoVO.getRecommenderOrgid());
        comPreNlsCreditInfo.setStatus(preNlsCreditInfoVO.getStatus());
        comPreNlsCreditInfo.setReAmount(preNlsCreditInfoVO.getReAmount());
        comPreNlsCreditInfo.setReYRate(preNlsCreditInfoVO.getReYRate());
        comPreNlsCreditInfo.setCertNo(preNlsCreditInfoVO.getCertNo());
        comPreNlsCreditInfo.setMobileNo(preNlsCreditInfoVO.getMobileNo());
        comPreNlsCreditInfo.setCertName(preNlsCreditInfoVO.getCertName());
        comPreNlsCreditInfo.setCertType(preNlsCreditInfoVO.getCertType());
        comPreNlsCreditInfo.setRefuseReason(preNlsCreditInfoVO.getRefuseReason());
        comPreNlsCreditInfo.setRefuseCode(preNlsCreditInfoVO.getRefuseCode());
        return comPreNlsCreditInfo;
    }

    /**
     * 根据参数查询预授信申请记录
     *
     * @param psdCompositeQryReqBean 查询参数
     * @return
     */
    private PreNlsCreditInfoVO qryPreNlsCreditInfoByParam(PsdCompositeQryReqBean psdCompositeQryReqBean) throws Exception {
        //0、纳税识别号 1、渠道申请号 2、预授信申请号 3、授信申请流水号
        switch (psdCompositeQryReqBean.getParamType()) {
            case "0":
                List<PreNlsCreditInfoVO> preNlsCreditInfoVOS = preNlsCreditInfoService.queryByTaxNumber(psdCompositeQryReqBean.getApplySeq());
                if (preNlsCreditInfoVOS.isEmpty()) {
                    return null;
                }
                return preNlsCreditInfoVOS.stream().sorted((o1, o2) -> {
                    LocalDateTime localDateTime1 = LocalDateTime.parse(o1.getCreateTime(), DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
                    LocalDateTime localDateTime2 = LocalDateTime.parse(o2.getCreateTime(), DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
                    if (localDateTime1.isAfter(localDateTime2)) {
                        return -1;
                    }
                    if (localDateTime1.isBefore(localDateTime2)) {
                        return 1;
                    }
                    return 0;
                }).limit(1).collect(Collectors.toList()).get(0);
            case "1":
                PreNlsCreditInfoVO param1 = new PreNlsCreditInfoVO();
                param1.setChannelApplyNo(psdCompositeQryReqBean.getApplySeq());
                return preNlsCreditInfoService.queryByChannelApplyNo(param1);
            case "2":
                PreNlsCreditInfoVO param2 = new PreNlsCreditInfoVO();
                param2.setApplySeq(psdCompositeQryReqBean.getApplySeq());
                return preNlsCreditInfoService.queryByPk(param2);
            case "3":
                NlsCreditInfoVO nlsCreditInfoVO = nlsCreditInfoService.queryByLmtApplySeq(psdCompositeQryReqBean.getApplySeq());
                if (Objects.isNull(nlsCreditInfoVO)) {
                    return null;
                }
                PreNlsCreditInfoVO param3 = new PreNlsCreditInfoVO();
                param3.setApplySeq(nlsCreditInfoVO.getPreLmtApplySeq());
                return preNlsCreditInfoService.queryByPk(param3);
            default:
                throw new Exception("不合法的参数类型");
        }
    }

    public EsbRespServiceBean successHandler(EsbReqServiceBean esbReqServiceBean, PsdCompositeQryRespBean psdCompositeQryRespBean) {
        // 返回代码
        psdCompositeQryRespBean.setRetCode(ESBConstant.SUCCESS);
        // 返回信息
        psdCompositeQryRespBean.setRetMsg("查询成功");
        return EsbRespServiceBeanCreator.buildesbRespServiceBean(esbReqServiceBean,
                JSONObject.toJSONString(psdCompositeQryRespBean, SerializerFeature.WriteMapNullValue, SerializerFeature.WriteMapNullValue, SerializerFeature.WriteNullListAsEmpty, SerializerFeature.WriteNullStringAsEmpty, SerializerFeature.WriteNullNumberAsZero),
                EsbSysHeadEnums.RetStEnum.SUCCESS.getCode(),
                EsbBizEnums.RetCodeEnum.SUCCESS.getVALUE(),
                EsbBizEnums.RetCodeMsg.SUCCESS_MSG.getVALUE());
    }

    public EsbRespServiceBean failureHandler(EsbReqServiceBean esbReqServiceBean, PsdCompositeQryRespBean psdCompositeQryRespBean, Exception exception, EsbRetCodeStandard esbRetCodeStandard, String respFaliStr) {
        logger.error("普税贷预授信申请信息查询接口出现异常，异常信息：" + exception.getMessage());
        psdCompositeQryRespBean.setRetCode(esbRetCodeStandard.getValue());
        psdCompositeQryRespBean.setRetMsg(respFaliStr);
        exception.printStackTrace();
        return EsbRespServiceBeanCreator.buildesbRespServiceBean(esbReqServiceBean,
                JSONObject.toJSONString(psdCompositeQryRespBean, SerializerFeature.WriteMapNullValue, SerializerFeature.WriteNullListAsEmpty, SerializerFeature.WriteNullStringAsEmpty, SerializerFeature.WriteNullNumberAsZero, SerializerFeature.WriteMapNullValue),
                EsbSysHeadEnums.RetStEnum.FAILURE.getCode(),
                esbRetCodeStandard.getValue(),
                exception.getMessage());
    }

}